//
//  SCAudioPlayer.m
//  SCAudioPlayer
//
//  Created by 盛超 on 2018/7/25.
//  Copyright © 2018年 盛超. All rights reserved.
//

#import "BKAudioPlayer.h"

@interface BKAudioPlayer ()

@property (nonatomic ,strong) AVPlayerItem *playerItem;
@property (nonatomic, strong) id timeObserve;// 时间观察
@property (nonatomic, assign) BOOL isPlay;/*!*播放或者暂停*/

@end

@implementation BKAudioPlayer

+ (instancetype)sharedMPlayer
{
    static BKAudioPlayer *audioPlayer = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        audioPlayer = [[BKAudioPlayer alloc] init];
    });
    return audioPlayer;
}

- (void)playerUrl:(NSURL *)url seekTotime :(NSInteger)recordTime rateValue:(float)ratevalue{

    if (_player) {
        [self closePlayer];
    }
    
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    NSError * error;
    //BOOL success = [audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:&error];
    BOOL success = [audioSession setCategory:AVAudioSessionCategoryPlayback error:&error];
    if(!success)
    {
        NSLog(@"error doing outputaudioportoverride - %@", [error localizedDescription]);
    }
    
    self.playerItem = [[AVPlayerItem alloc] initWithURL:url];
    _ratevalue = ratevalue;//倍速
    //AVPlayer
    _player = [[AVPlayer alloc] initWithPlayerItem:self.playerItem];
    //指定时间播放,类似记忆播放,拖动进度条也用这个方法
    [_player seekToTime:CMTimeMake(recordTime, 1)];
    
    self.playerItem.audioTimePitchAlgorithm = AVAudioTimePitchAlgorithmTimeDomain;
    //如果想实现倍速播放,必须调用此方法
    [self enableAudioTracks:YES inPlayerItem:_playerItem];
    self.player.rate = _ratevalue;
    //添加通知，拔出耳机后暂停播放
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(routeChange:) name:AVAudioSessionRouteChangeNotification object:nil];
}

- (void)setUrl:(NSURL *)url {
    url = url;
    
    if (_player) {
        [self closePlayer];
    }
    
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    NSError * error;
    BOOL success = [audioSession setCategory:AVAudioSessionCategoryPlayback error:&error];
    if(!success)
    {
        NSLog(@"error doing outputaudioportoverride - %@", [error localizedDescription]);
    }
    
    self.playerItem = [[AVPlayerItem alloc] initWithURL:url];
    _player = [[AVPlayer alloc] initWithPlayerItem:self.playerItem];
    
    self.playerItem.audioTimePitchAlgorithm = AVAudioTimePitchAlgorithmTimeDomain;
    //如果想实现倍速播放,必须调用此方法
    [self enableAudioTracks:YES inPlayerItem:_playerItem];
    self.player.rate = _ratevalue;
   // [_player play];
}

/**
 *  根据playerItem，来添加移除观察者
 *
 *  @param playerItem playerItem
 */
- (void)setPlayerItem:(AVPlayerItem *)playerItem
{
    //如果初始化的item与当前item相等,则不做操作
    if (_playerItem == playerItem) {
        return;
    }
    //如果当前item不为空,移除里面的属性观察
    if (_playerItem) {
        [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:_playerItem];
        [_playerItem removeObserver:self forKeyPath:@"status"];
        [_playerItem removeObserver:self forKeyPath:@"loadedTimeRanges"];
    }
    _playerItem = playerItem;
    if (playerItem) {
        //当前音频播放完毕监听,我这里写的代理,方便数据传递
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayDidEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem];
        //监听播放器状态
        [playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
        //除了播放器状态,还可以监听缓冲状态:无缓冲playbackBufferEmpty,缓冲足够可以播放:playbackBufferEmpty等,具体状态可以百度查找
        [playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
    }
}

//观察播放器状态
- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSString*, id> *)change context:(nullable void *)context {
    
    if ([keyPath isEqualToString:@"status"]) {
        AVPlayerItemStatus status = _playerItem.status;
        switch (status) {
            case AVPlayerItemStatusReadyToPlay:
            {
                NSLog(@"AVPlayerItemStatusReadyToPlay");
//                self.playerItem.audioTimePitchAlgorithm = AVAudioTimePitchAlgorithmTimeDomain;
//                //如果想实现倍速播放,必须调用此方法
//                [self enableAudioTracks:YES inPlayerItem:_playerItem];
//                self.player.rate = _ratevalue;
                //增加一个时间观察,为了实时拿到当前播放时间,刷新UI,锁屏操作等
                [self addTimeObserve];
//                [self.player pause];
            }
                break;
            case AVPlayerItemStatusUnknown:
            {
                NSLog(@"AVPlayerItemStatusUnknown");
            }
                break;
            case AVPlayerItemStatusFailed:
            {
                NSLog(@"AVPlayerItemStatusFailed");
                NSLog(@"%@",_playerItem.error);
            }
                break;
                
            default:
                break;
        }
    }
    
    AVPlayerItem * songItem = object;
    if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
        NSArray * array = songItem.loadedTimeRanges;
        CMTimeRange timeRange = [array.firstObject CMTimeRangeValue]; //本次缓冲的时间范围
        NSTimeInterval totalBuffer = CMTimeGetSeconds(timeRange.start) + CMTimeGetSeconds(timeRange.duration); //缓冲总长度
        NSLog(@"共缓冲%.2f",totalBuffer);
        if (_totalTime==0) {
            NSInteger currentTime = (NSInteger)CMTimeGetSeconds([songItem currentTime]);
            CGFloat totalTime = (CGFloat)songItem.duration.value / songItem.duration.timescale;
            //播放器时间代理
            [self.delegateM audioUpdateWith:currentTime Totaltime:totalTime];
            _totalTime = totalTime;
            _currentTime = currentTime;
        }
        
    }
}

//每一秒刷新UI
- (void)addTimeObserve{
    __weak typeof(self) weakSelf = self;
    if (self.player) {
        if (self.timeObserve) {
            @try {
                [self.player removeTimeObserver:self.timeObserve];
                self.timeObserve = nil;
            }@catch(id anException) {
                NSLog(@"PlayanException=%@",anException);
            }
        }
        
        CMTime interval = CMTimeMakeWithSeconds(0.01, 100);
        self.timeObserve = [self.player addPeriodicTimeObserverForInterval:interval queue:nil usingBlock:^(CMTime time){
            AVPlayerItem *currentItem = weakSelf.playerItem;
            NSArray *loadedRanges = currentItem.seekableTimeRanges;
            CGFloat currentTime = (CGFloat)CMTimeGetSeconds([currentItem currentTime]);
           // NSLog(@"currentTime=%f",currentTime);
           // NSLog(@"%@",currentItem);
            if (currentItem!=nil) {
                CGFloat totalTime = (CGFloat)currentItem.duration.value / currentItem.duration.timescale;
                if (self.delegateM && [self.delegateM respondsToSelector:@selector(audioUpdateWith:Totaltime:)]) {
                    //播放器时间代理
                   //  NSLog(@"currentTime=%ld,totalTime=%lf",currentTime,totalTime);
                    [weakSelf.delegateM audioUpdateWith:currentTime Totaltime:totalTime];
                }
                //根据系统方法来判断播放器状态,供外部属性调用实时刷新UI,比如:外部播放器按钮状态可根据可状态播放,点击播放还是暂停,也可以通过此状态判断
                if(@available(iOS 10.0, *)) {
                    if (self.player.timeControlStatus == AVPlayerTimeControlStatusPlaying) {
                        _playerState = MAudioStatePlaying;
                    }
                    if (self.player.timeControlStatus == AVPlayerTimeControlStatusPaused) {
                        _playerState = MAudioStatePaused;
                    }
                    if (self.player.timeControlStatus == AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate) {
                        _playerState = MAudioStateWaiting;
                    }
                }
                
                if (loadedRanges.count > 0 && currentItem.duration.timescale != 0) {
                    _totalTime = totalTime;
                    _currentTime = currentTime;
                }
            }
        }];
    }
}

- (void)moviePlayDidEnd:(NSNotification*)noti {
    if (self.delegateM && [self.delegateM respondsToSelector:@selector(audioPlayEnd)]) {
        _playerState = MAudioStateEnd;
        [self.delegateM audioPlayEnd];
    }
}

//倍速切换方法
- (void)enableAudioTracks:(BOOL)enable inPlayerItem:(AVPlayerItem*)playerItem
{
    for (AVPlayerItemTrack *track in playerItem.tracks)
    {
        if ([track.assetTrack.mediaType isEqual:AVMediaTypeAudio])
        {
            track.enabled = enable;
        }
    }
}

//播放暂停
- (void)playerPaused {
    [self.player pause];
    _playerState = MAudioStatePaused;
}
//播放继续
- (void)playerPlay {
    [self.player play];
    self.player.rate = _ratevalue;
}

//关闭播放器,记得移除通知,置空播放器
- (void)closePlayer {
    [self.player pause];
    if (self.timeObserve) {
        @try {
            [self.player removeTimeObserver:self.timeObserve];
            self.timeObserve = nil;
        }@catch(id anException) {
            NSLog(@"anException=%@",anException);
        }
    }
    [self.player.currentItem cancelPendingSeeks];
    [self.player.currentItem.asset cancelLoading];
    self.playerItem = nil;
    [self.player replaceCurrentItemWithPlayerItem:nil];
    _player = nil;
    //self.delegateM = nil;
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

#pragma mark - 耳机监听
-(void)routeChange:(NSNotification *)notification{
    NSDictionary *dic=notification.userInfo;
    int changeReason= [dic[AVAudioSessionRouteChangeReasonKey] intValue];
    //等于AVAudioSessionRouteChangeReasonOldDeviceUnavailable表示旧输出不可用
    if (changeReason==AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {
        AVAudioSessionRouteDescription *routeDescription=dic[AVAudioSessionRouteChangePreviousRouteKey];
        AVAudioSessionPortDescription *portDescription= [routeDescription.outputs firstObject];
        //原设备为耳机则继续
        if ([portDescription.portType isEqualToString:@"Headphones"]) {
            if (_playerState!=MAudioStateEnd && _playerState!=MAudioStatePaused) {
                [self.player play];
            }
        }
    }
}


@end
